﻿Ext.form.FormPanel = Ext.extend(Ext.Panel, {

    standardSubmit: false,

    componentCls: 'x-form',


    url: undefined,


    baseParams: undefined,


    waitTpl: new Ext.XTemplate(
        '<div class="{cls}">{message}&hellip;</div>'
    ),


    submitOnAction: true,

    getElConfig: function () {
        return Ext.apply(Ext.form.FormPanel.superclass.getElConfig.call(this), {
            tag: 'form'
        });
    },


    initComponent: function () {
        this.addEvents(

            'submit',

             'beforesubmit',

             'exception'
        );

        Ext.form.FormPanel.superclass.initComponent.call(this);

        this.on('action', this.onFieldAction, this);
    },


    afterRender: function () {
        Ext.form.FormPanel.superclass.afterRender.call(this);
        this.el.on('submit', this.onSubmit, this);
    },


    onSubmit: function (e, t) {
        if (!this.standardSubmit || this.fireEvent('beforesubmit', this, this.getValues(true)) === false) {
            if (e) {
                e.stopEvent();
            }
        }
    },


    onFieldAction: function (field) {
        if (this.submitOnAction) {
            field.blur();
            this.submit();
        }
    },



    submit: function (options) {
        var form = this.el.dom || {},
            formValues

        options = Ext.apply({
            url: this.url || form.action,
            submitDisabled: false,
            method: form.method || 'post',
            autoAbort: false,
            params: null,
            waitMsg: null,
            headers: null,
            success: null,
            failure: null
        }, options || {});

        formValues = this.getValues(this.standardSubmit || !options.submitDisabled);

        if (this.standardSubmit) {
            if (form) {
                if (options.url && Ext.isEmpty(form.action)) {
                    form.action = options.url;
                }

                form.method = (options.method || form.method).toLowerCase();

                if (this.fireEvent('beforesubmit', this, formValues, options) !== false) {
                    form.submit();
                }
            }
            return null;
        }

        if (this.fireEvent('beforesubmit', this, formValues, options) !== false) {
            if (options.waitMsg) {
                this.showMask(options.waitMsg);
            }

            return Ext.Ajax.request({
                url: options.url,
                method: options.method,
                rawData: Ext.urlEncode(Ext.apply(
                    Ext.apply({}, this.baseParams || {}),
                    options.params || {},
                    formValues
                )),
                autoAbort: options.autoAbort,
                headers: Ext.apply(
                   { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' },
                    options.headers || {}),
                scope: this,
                callback: function (callbackOptions, success, response) {
                    var responseText = response.responseText;
                    this.hideMask();

                    if (success) {

                        response = Ext.decode(responseText);
                        success = !!response.success;

                        if (success) {
                            if (Ext.isFunction(options.success)) {
                                options.success.call(options.scope || this, this, response, responseText);
                            }

                            this.fireEvent('submit', this, response);
                            return;
                        }
                    }

                    if (Ext.isFunction(options.failure)) {
                        options.failure.call(options.scope || this, this, response, responseText);
                    }

                    this.fireEvent('exception', this, response);
                }
            });
        }
    },


    loadRecord: function (instance) {
        if (instance && instance.data) {
            this.setValues(instance.data);


            this.record = instance;
        }

        return this;
    },


    loadModel: function () {
        return this.loadRecord.apply(this, arguments);
    },


    getRecord: function () {
        return this.record;
    },


    updateRecord: function (instance, enabled) {
        var fields, values, name;

        if (instance && (fields = instance.fields)) {
            values = this.getValues(enabled);
            for (name in values) {
                if (values.hasOwnProperty(name) && fields.containsKey(name)) {
                    instance.set(name, values[name]);
                }
            }
        }
        return this;
    },



    setValues: function (values) {
        var fields = this.getFields(),
             name,
             field,
             value;

        values = values || {};

        for (name in values) {
            if (values.hasOwnProperty(name)) {
                field = fields[name];
                value = values[name];
                if (field) {
                    if (Ext.isArray(field)) {
                        field.forEach(function (field) {
                            if (Ext.isArray(values[name])) {
                                field.setChecked((value.indexOf(field.getValue()) != -1));
                            } else {
                                field.setChecked((value == field.getValue()));
                            }
                        });
                    } else {
                        if (field.setChecked) {
                            field.setChecked(value);
                        } else {
                            field.setValue(value);
                        }
                    }
                }
            }
        }

        return this;
    },


    getValues: function (enabled) {
        var fields = this.getFields(),
            field,
            values = {},
            name;

        for (name in fields) {
            if (fields.hasOwnProperty(name)) {
                if (Ext.isArray(fields[name])) {
                    values[name] = [];

                    fields[name].forEach(function (field) {
                        if (field.isChecked() && !(enabled && field.disabled)) {
                            if (field instanceof Ext.form.Radio) {
                                values[name] = field.getValue();
                            } else {
                                values[name].push(field.getValue());
                            }
                        }
                    });
                } else {
                    field = fields[name];

                    if (!(enabled && field.disabled)) {
                        if (field instanceof Ext.form.Checkbox) {
                            values[name] = (field.isChecked()) ? field.getValue() : null;
                        } else {
                            values[name] = field.getValue();
                        }
                    }
                }
            }
        }

        return values;
    },


    reset: function () {
        this.getFieldsAsArray().forEach(function (field) {
            field.reset();
        });

        return this;
    },


    enable: function () {
        this.getFieldsAsArray().forEach(function (field) {
            field.enable();
        });

        return this;
    },


    disable: function () {
        this.getFieldsAsArray().forEach(function (field) {
            field.disable();
        });

        return this;
    },

    getFieldsAsArray: function () {
        var fields = [];

        var getFieldsFrom = function (item) {
            if (item.isField) {
                fields.push(item);
            }

            if (item.isContainer) {
                item.items.each(getFieldsFrom);
            }
        };

        this.items.each(getFieldsFrom);

        return fields;
    },


    getFields: function (byName) {
        var fields = {},
            itemName;

        var getFieldsFrom = function (item) {
            if (item.isField) {
                itemName = item.getName();

                if ((byName && itemName == byName) || typeof byName == 'undefined') {
                    if (fields.hasOwnProperty(itemName)) {
                        if (!Ext.isArray(fields[itemName])) {
                            fields[itemName] = [fields[itemName]];
                        }

                        fields[itemName].push(item);
                    } else {
                        fields[itemName] = item;
                    }
                }

            }

            if (item.isContainer) {
                item.items.each(getFieldsFrom);
            }
        };

        this.items.each(getFieldsFrom);

        return (byName) ? (fields[byName] || []) : fields;
    },

    getFieldsFromItem: function () {

    },

    showMask: function (cfg, target) {
        cfg = Ext.isString(cfg) ? { message: cfg} : cfg;

        if (cfg && this.waitTpl) {
            this.maskTarget = target = Ext.get(target || cfg.target) || this.el;
            target && target.mask(this.waitTpl.apply(cfg));
        }
        return this;
    },


    hideMask: function () {
        if (this.maskTarget) {
            this.maskTarget.unmask();
            delete this.maskTarget;
        }
        return this;
    }
});


Ext.form.FormPanel.prototype.load = Ext.form.FormPanel.prototype.loadModel;

Ext.reg('formpanel', Ext.form.FormPanel);


Ext.reg('form', Ext.form.FormPanel);